package com.ssi.mrms.mail;

import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.activation.DataSource;
import javax.mail.internet.MimeMessage;
import javax.mail.util.ByteArrayDataSource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

@Service("EmailService")
public class EmailService {

	private static final Logger logger = Logger.getLogger(EmailService.class);

	@Autowired
	private JavaMailSenderImpl mailSender = null;

	public void setMailSender(JavaMailSenderImpl mailSender) {
		this.mailSender = mailSender;
	}

	public void sendEmail(Email email) {
		logger.info("Accept mail : " + email.getTo());
		mailThreadPool.execute(new SendMail(email));
	}

	class SendMail implements Runnable {

		Email email;

		public SendMail(final Email email) {
			this.email = email;
		}

		@Override
		public void run() {
			logger.info("Run send mail : " + email.getTo());
			try {
				MimeMessage mimeMessage = mailSender.createMimeMessage();
				// use the true flag to indicate you need a multipart message
				boolean hasAttachments = (email.getAttachments() != null && email.getAttachments().size() > 0);
				MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, hasAttachments, "UTF-8");
				helper.setTo(email.getTo());
				helper.setFrom(email.getFrom());
				helper.setSubject(email.getSubject());
				helper.setText(email.getText(), true);
				if (email.getCc() != null && email.getCc().length > 0) {
					helper.setCc(email.getCc());
				}
				if (email.getBcc() != null && email.getBcc().length > 0) {
					helper.setBcc(email.getBcc());
				}
				List<Attachment> attachments = email.getAttachments();
				if (attachments != null && attachments.size() > 0) {
					for (Attachment attachment : attachments) {
						String filename = attachment.getFilename();
						DataSource dataSource = new ByteArrayDataSource(attachment.getData(), attachment.getMimeType());
						if (attachment.isInline()) {
							helper.addInline(filename, dataSource);
						} else {
							helper.addAttachment(filename, dataSource);
						}
					}
				}
				mailSender.send(mimeMessage);
				logger.info("Complete send mail : " + email.getTo());
			} catch (Exception e) {
				logger.error(e.toString(), e);
			}
		}
	}

	// Sets the initial threadpool size to 3
	private static final int CORE_POOL_SIZE = 3;

	// Sets the maximum threadpool size to 3
	private static final int MAXIMUM_POOL_SIZE = 3;

	// Sets the amount of time an idle thread will wait for a task before
	// terminating
	private static final int KEEP_ALIVE_TIME = 3;

	// Sets the Time Unit to seconds
	private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.MINUTES;

	// A queue of Runnables for the sendmail pool
	private final LinkedBlockingQueue<Runnable> mailQueue = new LinkedBlockingQueue<Runnable>();

	// A managed pool of background upload threads
	private final ThreadPoolExecutor mailThreadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,
			KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, mailQueue) {

		@Override
		protected void afterExecute(Runnable r, Throwable t) {
			super.afterExecute(r, t);

			if (getActiveCount() == 1 && getQueue().size() == 0) {
				// we're the last Runnable around + queue is empty, service can
				// be
				// safely stopped.

			}
		}
	};

}